using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace WinSAG
{
    public partial class WSF_mainFrm 
    {
        /// <summary>
        /// Adds the log line to log_listbox.
        /// </summary>
        /// <param name="s">The s.</param>
        internal void addLogLine(string s)
        {
            // TODO: Make this more sophi later. This will be slow
            // for lots of messages
            WSF_logMessages.Items.Insert(0, s);
        }

        /// <summary>
        /// Handles the Click event of the findDuplicatesToolStripMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void findDuplicatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string cmdLine;

            if (false == checkIfToolExists())
            {
                MessageBox.Show("[TOOL_ERR] Cannot find tool. Check the path.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                addLogLine("[TOOL_ERR] Cannot find tool. Check the path.");
                return;
            }

            globals.showProgressWindow();
            try
            {
                if (globals.CurrentProject == null)
                    return; // TODO: Control shd not have come here. ASSERT!!!                     

                // 1) Get the command line
                cg = new CommandLineGenerator(globals.CurrentProject);
                cmdLine = cg.getCommandLine();
                globals.TmpFile = cg.ResultsFilename; // Store the filename so that we can delete it later.

                // 2) Run the SAT to collect results
                BackgroundWorker bgworker = new BackgroundWorker();
                bgworker.DoWork += new DoWorkEventHandler(satExecuteThread);
                bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(satExitHandler);
                bgworker.RunWorkerAsync(cmdLine);
            }
            catch (Exception e1)
            {
                addLogLine("[SAT_EXEC_ERR] " + e1.Message + "," + e1.ToString());
            }

        }

        /// <summary>
        /// Sats the exit handler.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        void satExitHandler(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                MessageBox.Show("[SAT_RUN_ERROR] " + e.Error.Source + " - " + e.Error.Message + " - " + e.Error.InnerException);
            }
            else
            {
                if (globals.SATGotKilled == true)
                {
                    string msg = @"Tool had to be terminated. Please try again later.";
                    addLogLine(@"[SAT_RUN_ERROR] " + msg);
                    MessageBox.Show(msg, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // TODO: Do we need to check for Cancelled??
                showResults();

                // Turn off the progress bar
                globals.hideProgressWindow();

                // Enable the print_results option now
                setState(WSU_Literals.WSF_UI_STATE.WSF_UI_STATE_RESULTSAVAILABLE);

                // Try to clean up
                try 
                {
                    File.Delete(globals.TmpFile);
                }
                catch (Exception e1)
                {
                    addLogLine("[TMPFILE_DEL_ERR] " + e1.Message + ", Please clean it up later.");
                }
                finally
                {
                    globals.TmpFile = null;
                }
            }
        }

        /// <summary>
        /// Shows the results in the results tab.
        /// </summary>
        private void showResults()
        {
            // Command has completed successfully. Load the results now.
            WSU_ProcessResults pr = new WSU_ProcessResults(cg.ResultsFilename, globals.getToolStyleSheet());
            
            // Load the generated o/p from SAT and convert it in to XHTML
            pr.processResults();

            // Filename to store the final XHTML 
            string filename = Path.GetDirectoryName(globals.CurrentProject.SourcePath).TrimEnd(new char[] { '\\' }) 
                + @"\" + globals.CurrentProject.ProjectName + @".html";
            pr.saveResultsToFile(filename);

            // Open the generated o/p in the results browser
            object empty = System.Reflection.Missing.Value;
            WSF_results.Navigate(filename, ref empty, ref empty, ref empty, ref empty);
        }

        /// <summary>
        /// Sats the execute thread.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        void satExecuteThread(object sender, DoWorkEventArgs e)
        {
            // Invoke the tool in the bground thread now
            executeSAT(e.Argument as string);
        }

        /// <summary>
        /// Executes the SAT.
        /// </summary>
        /// <param name="cmdLine">The CMD line.</param>
        private void executeSAT(string cmdLine)
        {
            Process sat = new Process();
            sat.StartInfo.FileName = globals.getToolToExecute();
            sat.StartInfo.CreateNoWindow = true;
            sat.StartInfo.UseShellExecute = false;
            sat.StartInfo.RedirectStandardInput = false;
            sat.StartInfo.RedirectStandardOutput = false;
            sat.StartInfo.ErrorDialog = true;
            sat.StartInfo.WorkingDirectory = Path.GetDirectoryName(globals.getToolToExecute());//Path.GetDirectoryName(Application.ExecutablePath);
            sat.StartInfo.Arguments = cmdLine;
            try
            {
                if (sat.Start() == true)
                {
                    if (false == sat.WaitForExit(globals.getToolMaxExecTime()))
                    {
                        // If we are here, that means the SAT is taking more time than it is 
                        // supposed to. Terminate the application
                        sat.Kill();
                        sat.Close();

                        // Mark the process as forcefully terminated
                        globals.SATGotKilled = true;
                    }
                }
            }
            catch (Exception e1)
            {
                MessageBox.Show("[SAT_EXEC_ERR] " + e1.Message + "," + e1.ToString(), "Exception");
            }
        }

        /// <summary>
        /// Checks if tool exists.
        /// </summary>
        /// <returns></returns>
        private bool checkIfToolExists()
        {
            try
            {
                string processName = globals.getToolToExecute();
                return File.Exists(processName);
            }
            catch (System.Exception)
            {
                return false;
            }
        }
    }
}
